package com.rivues.module.platform.web.auth;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.aspectj.weaver.patterns.ExactAnnotationTypePattern;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.Auth;
import com.rivues.module.platform.web.model.DataDic;
import com.rivues.module.platform.web.model.Organ;
import com.rivues.module.platform.web.model.Role;
import com.rivues.module.platform.web.model.RoleGroup;
import com.rivues.module.platform.web.model.User;
import com.rivues.module.platform.web.model.UserOrgan;
import com.rivues.module.platform.web.model.UserRole;
import com.rivues.module.report.web.model.PublishedReport;
import com.rivues.util.iface.authz.UserAuthzFactory;
import com.rivues.util.iface.report.ReportFactory;

@Service
public class AuthInterfaceImpl  implements AuthInterface{
	/**
	 * log4j
	 */
	private final Logger logger = LoggerFactory.getLogger(AuthInterfaceImpl.class);
	/**
	 * 增加权限拥有着列表(选择组织是调用)
	 */
	public void  addOwnerList(String resourceid,String ids,String orgi,String ownerType,String isDic) throws Exception{
		List<Auth> list = new ArrayList<Auth>();
		for(String tmp :ids.split(",")){
			List tmpList = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("resourceid", resourceid)).add(Restrictions.eq("ownerid", tmp)));
			if (tmpList != null && tmpList.size()>0){
				String ownername = Auth.OWNER_TYPE_ORGAN.equals(ownerType)?"组织":Auth.OWNER_TYPE_ROLE.equals(ownerType)?"角色":"用户";
				String resourcename = Auth.RESOURCE_DIC_N.equals(isDic)?"目录":"报表";
			//	throw new Exception("该"+resourcename+"已经分配给"+ownername+"，请重新分配.");
			}
			Auth auth = new Auth();
			auth.setResourceid(resourceid);
			auth.setCreatetime(new Date());
			auth.setOrgi(orgi);
			auth.setOwnerid(tmp);
			auth.setOwnertype(ownerType);
			auth.setResourcedic(isDic);
			auth.setResourcetype(Auth.RESOURCE_TYPE_REPORT);
			list.add(auth);
			RivuDataContext.getService().execByHQL("delete Auth where resourceid='"+resourceid+"' and ownerid='"+tmp+"'");
		}
		RivuDataContext.getService().saveBat(list);
	}
	
	
	/**
	 * 更新资源权限
	 * @param resourceid
	 * @param list
	 * @throws Exception
	 */
	public void updateAuth(String resourceid,List<Auth> list)  throws Exception{
		try{
			RivuDataContext.getService().execByHQL("update Auth set authtype='',authread='' where resourceid='"+resourceid+"'");
			for(Auth auth : list){
				RivuDataContext.getService().execByHQL("update Auth set authtype='"+auth.getAuthtype()+"' , authread='"+auth.getAuthread()+"' where resourceid='"+resourceid+"'  and ownerid='"+auth.getOwnerid()+"'");
			}
		}catch(Exception ce){
			ce.printStackTrace();
			logger.error("更新报表权限出错，错误信息为:"+ce.getMessage(),ce);
		}
	}
	
	
	/**
	 * 目录鉴权  ， 鉴权规则：
	 * 		1、当前用户所在的 组织结构 和角色列表
	 * 		2、当前目录授权给 那些角色、组织机构
	 * 		3、当前用户是目录的创建人
	 * 		4、当前用户是 系统的超级管理员
	 * 		5、目录权限获取为 遍历 上级目录到  目录ID为  0  的 所有 ID列表
	 * @param dic
	 * @param user
	 */
	public List<Auth> filterAuth(DataDic dic,User user, List<DataDic> dicList , String orgi , String authType){
		List<Auth> authList = new ArrayList();
		try{
			/**
			 * 第一步，获取用户的 所有 机构ID、 角色ID、用户ID
			 */
			List<String> userIDS = new ArrayList<String>();
			for(Organ organ : user.getOrganList()){
				userIDS.add(organ.getId()) ;
				userIDS.add(organ.getName()) ;
			}
			for(Role role : user.getRoleList()){
				userIDS.add(role.getId()) ;
				userIDS.add(role.getName()) ;
			}
			userIDS.add(user.getId()) ;
			userIDS.add(user.getUsername()) ;
			/**
			 * 第二步 ， 获取用户从当前到 根节点所有的 目录ID
			 */
			List<String> dicIDS = new ArrayList<String>();
			dicIDS.add(dic.getId()) ;
			DataDic curdic = dic ; 
			while(!"0".equals(curdic.getParentid()) && !"0".equals(curdic.getId()) && dicList!=null){
				boolean find = false ;
				for(DataDic tempDic : dicList){
					if(tempDic.getId().equals(curdic.getParentid())){
						curdic = tempDic ;
						find = true ;
						break ;
					}
				}
				dicIDS.add(curdic.getId()) ;
				if((curdic.getType()!=null && "true".equals(curdic.getType())) || !find){
					break ;
				}
			}
			if(curdic.getParentid()!=null && !(curdic.getType()!=null && "true".equals(curdic.getType()))){
				dicIDS.add(curdic.getParentid()) ;
			}
			dicIDS.add(curdic.getId()) ;
			/**
			 * 第三步：找到 UserIDS 和 DicIDS 在 Auth表里的全部授权记录
			 */
			if(dicIDS.size() != 0 && userIDS.size() !=0){
				if(authType!=null && authType.equals(RivuDataContext.AuthTypeEnum.DIC.toString())){
					authList = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourcetype",Auth.RESOURCE_TYPE_DIC)).add(Restrictions.in("resourceid",dicIDS)).add(Restrictions.in("ownerid", userIDS)));
					dic.setAuthList(authList) ;
				}else{
					/**
					 * 查找当前目录下所有报表的授权
					 */
					authList = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.or( Restrictions.eq("resourcetype",Auth.RESOURCE_TYPE_REPORT) , Restrictions.eq("resourcetype",Auth.RESOURCE_TYPE_DIC))).add(Restrictions.in("dataid",dicIDS)).add(Restrictions.in("ownerid", userIDS)));
				}
			}
		}catch(Exception ce){
			logger.error("目录鉴权失败，错误信息为:"+ce.getMessage(),ce);
		}
		return authList ;
	}
	
	
	
	/**
	 * 获取对目录的授权信息
	 * @param reportid
	 * @return
	 */
	public List<Auth> getDicAuthList(String dicid,String orgi){
		return getAllAuthList(dicid, orgi);
	}
	
	
	/**
	 * 根据条件获取权限信息
	 */
	public List<Auth> getAuthlist(String resourceid,String resourcetype,String ownerid,String ownertype){
		DetachedCriteria criteria = DetachedCriteria.forClass(Auth.class);
		if(resourceid!=null){
			criteria.add(Restrictions.eq("resourceid", resourceid));
		}
		if(resourcetype!=null){
			criteria.add(Restrictions.eq("resourcetype",resourcetype));
		}
		if(ownerid!=null){
			criteria.add(Restrictions.eq("ownerid",ownerid));
		}
		if(ownertype!=null){
			criteria.add(Restrictions.eq("ownertype",ownertype));
		}
		List<Auth> authList =RivuDataContext.getService().findAllByCriteria(criteria);	
		return authList;
	}
	/**
	 * 获取用户自己所有的权限，包括他的父级的权限（角色权限和机构权限）
	 * 注意：用户优先级>角色优先级>机构优先级，
	 * @param userid
	 * @return map的key值为resourceid_resourcetype类型；
	 */
	public Map<String, Auth> getUserSelfAuthlist(String userid){
		Map<String, Auth> map = new HashMap<String, Auth>();
		List<Auth> auths = null;
		List<UserOrgan> userorgans = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(UserOrgan.class).add(Restrictions.eq("userid",userid)));
		if(userorgans.size()>0){
			UserOrgan userorgan = userorgans.get(0);
			List<Organ> organs = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Organ.class).add(Restrictions.eq("id",userorgan.getOrganid())));
			if(organs.size()>0){
				auths = this.getAuthlist(null, null,organs.get(0).getName(), Auth.OWNER_TYPE_ORGAN);
				for (Auth auth : auths) {
					map.put(auth.getResourceid(), auth);
				}
			}
			
		}
		List<UserRole> userroles = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(UserRole.class).add(Restrictions.eq("userid",userid)));
		if(userroles.size()>0){
			UserRole userrole = userroles.get(0);
			auths = this.getAuthlist(null, null,userrole.getRole().getName(), Auth.OWNER_TYPE_ROLE);
			for (Auth auth : auths) {
				map.put(auth.getResourceid(), auth);
			}
		}
		List<User> users = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(User.class).add(Restrictions.eq("id",userid)));
		if(users.size()>0){
			auths = this.getAuthlist(null, null,users.get(0).getUsername(), Auth.OWNER_TYPE_USER);
			for (Auth auth : auths) {
				map.put(auth.getResourceid(), auth);
			}
		}
		
		
		return map;
	}
	
	
	/**
	 * 获取用户自己所有的权限，包括他的父级的权限（角色权限和机构权限）
	 * 注意：用户优先级>角色优先级>机构优先级，
	 * @param userid
	 * @return map的key值为resourceid_resourcetype类型；
	 */
	public Map<String, Auth> getUserSelfAuthlist(String userid,List<Auth> auths){
		Map<String, Auth> map = new HashMap<String, Auth>();
		List<UserOrgan> userorgans = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(UserOrgan.class).add(Restrictions.eq("userid",userid)));
		if(userorgans.size()>0){
			UserOrgan userorgan = userorgans.get(0);
			List<Organ> organs = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Organ.class).add(Restrictions.eq("id",userorgan.getOrganid())));
			if(organs.size()>0){
				for (Auth auth : auths) {
					if(auth.getOwnerid().equals(organs.get(0).getName())){
						map.put(auth.getResourceid(), auth);
					}
					
				}
			}
			
		}
		List<UserRole> userroles = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(UserRole.class).add(Restrictions.eq("userid",userid)));
		if(userroles.size()>0){
			UserRole userrole = userroles.get(0);
			for (Auth auth : auths) {
				if(auth.getOwnerid().equals(userrole.getRole().getName())){
					map.put(auth.getResourceid(), auth);
				}
			}
		}
		List<User> users = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(User.class).add(Restrictions.eq("id",userid)));
		if(users.size()>0){
			for (Auth auth : auths) {
				if(auth.getOwnerid().equals(users.get(0).getUsername())){
					map.put(auth.getResourceid(), auth);
				}
			}
		}
		
		
		return map;
	}
	
	/**
	 * 检查权限是否存在
	 * @param resourceid
	 * @param map
	 * @return
	 */
	public boolean checkIsAuth(String resourceid ,String resourcetype,String userid){
		boolean flag = true;
		Map<String, Auth> map = this.getUserSelfAuthlist(userid);
		Collection<Auth> values = map.values();
		Auth auth = null;
		Iterator iterator = values.iterator();
		while(iterator.hasNext()){
			auth =  (Auth)iterator.next();
			if(auth.getResourceid().equals(resourceid)&&auth.getResourcetype().equals(resourcetype)&&auth.getAuthread()!=null&&auth.getAuthread().equals(Auth.AUTH_NONE)){
				flag = false;
				break;
			}
		}
		
		return flag;
	}
	
	/**
	 * 检查权限是否存在
	 * @param resourceid
	 * @param map
	 * @return
	 */
	public boolean checkIsAuth(String resourceid ,String resourcetype,String userid,List<Auth> auths){
		boolean flag = true;
		if(auths!=null&&auths.size()>0){
			Map<String, Auth> map = this.getUserSelfAuthlist(userid,auths);
			Collection<Auth> values = map.values();
			Auth auth = null;
			Iterator iterator = values.iterator();
			while(iterator.hasNext()){
				auth =  (Auth)iterator.next();
				if(auth.getResourceid().equals(resourceid)&&auth.getResourcetype().equals(resourcetype)&&auth.getAuthread()!=null&&auth.getAuthread().equals(Auth.AUTH_NONE)){
					flag = false;
					break;
				}
			}
		}
		
		
		return flag;
	}
	
	
	
	
	/**
	 * 根据用户信息获取目录权限
	 * @param datadic
	 * @param user
	 * @return
	 * @throws Exception
	 */
	 private Set<String> getDicAuthListByUser(DataDic datadic,User user) throws Exception{
		 /**
	    	 * 目录列表，需要按照权限过滤目录，目录授权规则
	    	 * 1、我创建的目录
	    	 * 2、我是目录的管理员
	    	 * 3、我是当前目录上级的管理员
	    	 * 4、授权给我可以访问的报表
	    	 */
		 return this.getUserCommonAuth(datadic.getId(), datadic.getCreater(),datadic.getOrgi(), user);
		 
	 }

	
	
	/**
	 * 报表鉴权
	 * @param report
	 * @param user
	 */
	public void filterReportAuth(PublishedReport report,User user){
		List<DataDic> dicList = ReportFactory.getReportInstance().getAllReportDicList(report.getOrgi() , user , report.getTabtype()) ;
		DataDic dic = null ;
		for(DataDic tdic : dicList){
			if(tdic.getId().equals(report.getDicid())){
				dic = tdic ;
				break ;
			}
		}
		if(dic == null){
			dic = new DataDic() ;
			dic.setId("0") ;
			dic.setOrgi(report.getOrgi()) ;
		}
		report.setAuthList(this.filterAuth(dic, user, dicList, report.getOrgi(), RivuDataContext.AuthTypeEnum.REPORT.toString())) ;
	}
	
	/**
	 * 获取报表权限
	 * @param report
	 * @param user
	 * @return
	 * @throws Exception
	 */
	private Set<String> getReportAuthByUser(PublishedReport report,User user) throws Exception{
		return  this.getUserCommonAuth(report.getId(),report.getCreater(),report.getOrgi(),user); 
	}
	
	
	 /**
     * 获取用户对该报表的权限
     * @param report
     * @return
     */
    private Set<String> getUserCommonAuth(String resourceid,String creater,String orgi,User user) throws Exception{
    	Set<String> set = new HashSet<String>();
    	 //1、我创建的报表/目录/模型
    	if(user.getId().equals(creater)){
    		set.addAll(Auth.getAllReportAuth());
    		return set;
    	} 
    	
    	//5、授权给我可以访问的报表
    	//防止重复
    	//获取该报表的所有权限列表
    	List<Auth> authList =RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid",resourceid)));
    	if (authList != null && authList.size()>0){
			for(Auth tmp : authList){
				if(tmp.getOwnertype().equals(Auth.OWNER_TYPE_USER) && tmp.getOwnerid().equals(user.getId())) {
					//权限所有者类型为个人
					set.addAll(tmp.getAuthList());
				} else if(tmp.getOwnertype().equals(Auth.OWNER_TYPE_ORGAN) && includeUser(tmp.getOwnerid(),user)){
					//如果所有者类型为组织机构,报表可能分配给多个组织,会将所有组织的权限累加
					set.addAll(tmp.getAuthList());//1,2,3,4
				} else if(tmp.getOwnertype().equals(Auth.OWNER_TYPE_ROLE)){
				}
			}
			return set;
		}
		return set;
    }
    
    
    /**
     *	用户是否属于该组织
     * @param organid
     * @param userid
     * @return
     */
    private boolean includeUser(String targetOrginid,User user) throws Exception{
    	
    	/**
    	 * 1、用户所有的关联组织是否属于该组织下级组织(r3系统组织)
    	 * 2、用户归属组织是否属于该组织的下级组织，并且继承组织权限(um系统组织)
    	 * 3、用户是否属于该组织
    	 */
    	
    	Object targetOrgan = RivuDataContext.getService().getIObjectByPK(Organ.class,targetOrginid);
    	String targetOgranName = "根目录";
		if(targetOrgan != null){
			targetOgranName=((Organ)targetOrgan).getName();
		}
		return false;
		
//		
//		//3、人是否属于该组织
//		Organ organ = null;
//    	if( user.getOrganusers() != null &&  user.getOrganusers().size()>0){
//    		for(UserOrgan userOrgan : user.getOrganusers()){
//    			String orginid = userOrgan.getOrganid();
//    			while(organ == null){
//    				//关联组织是否属于目标组织的下级组织
//    				if (orginid.equals(targetOrginid)){
//    					organ = new Organ();
//    				} else {
//    					Organ tmp = (Organ)RivuDataContext.getService().getIObjectByPK(Organ.class, orginid);
//    					orginid = tmp.getParentid();
//    					if ("0".equals(tmp.getParentid())) organ = new Organ();
//    					
//    				}
//    			}
//    		}
//    	}
//    	return organ == null ? false : true;
    }
    
    /**
     * 获取已经授权的资源信息
     * @param resourceid
     * @param orgi
     * @return
     */
    private List<Auth>  getAllAuthList(String resourceid,String orgi){
		List<Auth> list= RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourceid", resourceid)));
		if (list != null && list.size()>0){
			for(Auth tmp : list){
				if(tmp.getOwnerid().length()>30){
					if(tmp.getOwnertype().equals(Auth.OWNER_TYPE_ROLE)){
						Object role =  RivuDataContext.getService().getIObjectByPK(Role.class, tmp.getOwnerid());
						if(role!= null)tmp.setOwnername(((Role)role).getName());
					} else if (tmp.getOwnertype().equals(Auth.OWNER_TYPE_ORGAN)){
						Object organ = RivuDataContext.getService().getIObjectByPK(Organ.class, tmp.getOwnerid());
						if(organ!= null)tmp.setOwnername(((Organ)organ).getName());
					} else if (tmp.getOwnertype().equals(Auth.OWNER_TYPE_ROLE_GROUP)){
						Object group = RivuDataContext.getService().getIObjectByPK(RoleGroup.class, tmp.getOwnerid());
						if(group!= null)tmp.setOwnername(((RoleGroup)group).getName());
					} else {
						//Auth.OWNER_TYPE_USER
						Object user = RivuDataContext.getService().getIObjectByPK(User.class, tmp.getOwnerid());
						if (user != null)tmp.setOwnername(((User)user).getUsername());
					}
				}
				
			}
		}
		return list;
    }
	
	/**
	 * 获取对该报表的授权资源
	 * @param reportid
	 * @return
	 */
	public List<Auth> getReportAuthList(String reportid,String orgi){
		return getAllAuthList(reportid, orgi);
	}

	/**
	 * 目录授权
	 */
	@Override
	public List<Auth> filterDicAuth(User user, String orgi, String authType) {
		List<Auth> authList = new ArrayList();
		try{
			/**
			 * 第一步，获取用户的 所有 机构ID、 角色ID、用户ID
			 */
			List<String> userIDS = new ArrayList<String>();
			for(Organ organ : user.getOrganList()){
				userIDS.add(organ.getId()) ;
				userIDS.add(organ.getName()) ;
			}
			for(Role role : user.getRoleList()){
				userIDS.add(role.getId()) ;
				userIDS.add(role.getName()) ;
			}
			userIDS.add(user.getId()) ;
			userIDS.add(user.getUsername()) ;
			/**
			 * 第三步：找到 UserIDS 和 DicIDS 在 Auth表里的全部授权记录
			 */
			if(userIDS.size() != 0){
				authList = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(Auth.class).add(Restrictions.eq("orgi",orgi)).add(Restrictions.eq("resourcetype",Auth.RESOURCE_TYPE_DIC)).add(Restrictions.in("ownerid", userIDS)));
			}
		}catch(Exception ce){
			logger.error("目录鉴权失败，错误信息为:"+ce.getMessage(),ce);
		}
		return authList ;
	}

}
